﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Web.Caching;

namespace Mindfor.Web
{
	/// <summary>
	/// Provides captcha key generation.
	/// </summary>
	[AttributeUsage(AttributeTargets.Method, AllowMultiple=false, Inherited=true)]
	public class CaptchaGenerateAttribute : FilterAttribute, IActionFilter
	{
		/// <summary>
		/// Gets or sets of attribute always generates new captcha key.
		/// If false then captcha key generated only when it is not found or captcha validation occured.
		/// Default = false.
		/// </summary>
		public bool AlwaysGenerateKey { get; set; }
		
		/// <summary>
		/// Calles by the MVC framework before action.
		/// </summary>
		public void OnActionExecuting(ActionExecutingContext filterContext)
		{
			// check if need to assign captcha key
			ViewDataDictionary vd = filterContext.Controller.ViewData;
			ModelStateDictionary modelState = filterContext.Controller.ViewData.ModelState;
			ModelState keyState = modelState[CaptchaManager.HtmlKeyName];
			ModelState textState = modelState[CaptchaManager.HtmlTextName];

			string key = vd[CaptchaManager.ViewDataKey] as string;
			bool keyError = keyState != null && keyState.Errors.Count > 0;
			bool textError = textState != null && textState.Errors.Count > 0;

			if (key == null || keyError || textError || AlwaysGenerateKey)
			{
				// no captcha yet => create new one
				string text = CaptchaManager.GenerateText();
				key = CaptchaManager.EncryptTextToKey(text);
				vd[CaptchaManager.ViewDataKey] = key;
			}

			// add key to cache to prevent key injection from html
			Cache c = filterContext.RequestContext.HttpContext.Cache;
			if (c[key] == null)
				c.Add(key, "My key value", null, Cache.NoAbsoluteExpiration, new TimeSpan(3, 0, 0), CacheItemPriority.Default, null);
		}

		/// <summary>
		/// Calles by the MVC framework after action.
		/// </summary>
		public void OnActionExecuted(ActionExecutedContext filterContext)
		{
		}
	}
}
